package world;

import java.io.File;
import java.util.ArrayList;

import mini.hug.Hug;
import mini.reanimate.Reanimate;
import zulu.editorTest.EditorTest;
import zulu.test.*;
import bogus.minigame.MinigameBase;

public enum World {
	//LOAD("loader", MiniLoader.class), Loader is a special case and should not be registered here; attempting to load it would hypothetically cause an infinite loop
	TEST("test", Test.class),
	XBR("xbr", XBR.class),
	REBIRTH("BORGUS REANIMATED", Reanimate.class),
	HUG("BOGUS UNDERSTANDS CONSENT", Hug.class),
	EDITOR_TEST("editTest", EditorTest.class);
	
	public final String name;
	public final Class<?> spawner;
	final Stats stats;
	
	/**where (NAME) is the name to be displayed in-game, and (SPAWNER) is a child of Minigame that should be generated when the minigame begins*/
	private<T extends MinigameBase> World(String name, Class<T> spawner){
		this.name = name;
		this.spawner = spawner;
		
		//Fail-fast
		try {
		    spawner.getConstructor();
		} catch (Exception e) {
		    throw new RuntimeException(this+": could not retrieve a no-args constructor for: "+spawner, e);
		}
		
		this.stats = new Stats(this.name());
	}
	
	/**this returns whether this level has been unlocked*/
	public boolean getUnlock(){
		return this.stats.unlocked;
	}
	
	/**this returns the highscore of this level, a value of -1 indicates that the level is either unplayed or lacks a scoring system*/
	public int getHighscore(){
		return this.stats.highscore;
	}
	
	/**this method unlocks this level*/
	public void unlock(int id){
		this.stats.unlocked = true;
	}
	
	/**this method will set the highscore of this level to a given score (SCORE) if (SCORE) exceeds the previous score of the level. if
	 * this operation was performed then the function returns true.
	 */
	public boolean highscore(int score){
		if (score > getHighscore()){
			this.stats.highscore = score;
			return true;
		}
		return false;
	}
	
	/**write the contents of all World Stats to the savefile retrieved from Global.getSaveFile()*/
	public static void write(){
		ArrayList<Stats> stats = new ArrayList<Stats>();
		for (World w : values())
			stats.add(w.stats);
		Serial.writeObject(Global.SAVEFILE, stats);
	}
	
	@SuppressWarnings("unchecked")
	/**read the contents of the savefile at Global.getSaveFile() and match the retrieved Stats to the appropriate World*/
	public static void read(){
		File f = Global.SAVEFILE;
		if (f.exists()){
			ArrayList<Stats> stats = (ArrayList<Stats>)Serial.readObject(f)[0];
			for (Stats s : stats){
				for (World w : values()){
					if (w.name().equals(s.name))
						w.stats.load(s);
				}
			}
		}
	}

}
